/*CVS PARSER*/

%require "2.4.1"		/* Require bison 2.4.1 or later */
%start start			/* start symbol is named "start" */
%defines				/* write out a header file containing the token defines */
%skeleton "lalr1.cc"	/* use newer C++ skeleton file */
%name-prefix="Libcvs" 	/* namespace to enclose parser in */
%language "C++"
%define parser_class_name "LibcvsBisonParser"  /* set the parser's class identifier */

/* The driver is passed by reference to the parser and to the scanner. 
 * This provides a simple but effective pure interface, not relying on global variables. 
 */
%parse-param { Libcvs::LibcvsFlexScanner &scanner }
%lex-param   { Libcvs::LibcvsFlexScanner &scanner }

%error-verbose 			/* verbose error messages */

%code requires {
	// Forward-declare the Scanner class; the Parser needs to be assigned a 
	// Scanner, but the Scanner can't be declared without the Parser
	namespace Libcvs {

		class LibcvsFlexScanner;
		
	}
}

%code {
	// Prototype for the yylex function
	static int yylex(Libcvs::LibcvsBisonParser::semantic_type * yylval, Libcvs::LibcvsFlexScanner &scanner);
}


%{

#include <iostream>
#include <string>

#include "Libcvs.tab.hh"
#include "dotwriter/DotWriter.h"

using namespace std;

int yyerror(char *s);
int yylex(void);

DotWriter::Nodo nodotemporal;
DotWriter::DotWriter dotoutput;
%}

%union {
    int  			integerVal;
    double 			doubleVal;
    std::string*	stringVal;
}

/*Token declaration*/
%token END	0	"end of file"
%token <integerVal> INTEGER		"integer"
%token <doubleVal> 	DOUBLE		"double"
%token <stringVal> 	STRING		"string"
%token XMLHEADER
%token BCHANGELOG 	ECHANGELOG 
%token BENTRY		<stringVal> EENTRY
%token BDATE 		<stringVal> EDATE
%token BWEEK 		<stringVal> EWEEK
%token BTIME 		<stringVal> FTIME
%token BISO 		<stringVal> EISO
%token BAUTHOR		<stringVal> EAUTHOR
%token BFILE		<stringVal> EFILE
%token BNAME		<stringVal> ENAME
%token BCVSSTATE	<stringVal> ECVSSTATE
%token BREVISION	<stringVal> EREVISION
%token BTAG			<stringVal> ETAG
%token BMSG			<stringVal> EMSG
%token BCOMMONDIR	<stringVal> ECOMMONDIR
%token BTAGISODATE	<stringVal> ETAGISODATE
%token BTAGDATETAG	<stringVal> ETAGDATETAG
%token BTAGDATE		<stringVal> ETAGDATE
%token BBRANCH		<stringVal> EBRANCH
%%

start:		END | cvsparser start;
cvsparser: 	XMLHEADER changelog;
changelog: 	BCHANGELOG xentries ECHANGELOG {cout << "END PARSER" << endl; cerr << dotoutput<< endl;};
xentries:	xentries entries | entries;
entries:	entry {cout << "NEW ENTRY" << endl;}| tagdate;
entry:		BENTRY date weekdate time isodate author files msg EENTRY {dotoutput.addNodo(nodotemporal); nodotemporal.files="";};
date:		BDATE EDATE {cout << "date:" << *$2 << endl; delete $2; $2=NULL;};
weekdate:	BWEEK EWEEK	{cout << "week:" << *$2 << endl; delete $2; $2=NULL;};
time:		BTIME FTIME	{cout << "time:" << *$2 << endl; delete $2; $2=NULL;};
isodate:	BISO EISO	{cout << "isod:" << *$2 << endl; nodotemporal.timestamp=*$2; nodotemporal.revision=*$2; delete $2; $2=NULL;};
author:		BAUTHOR EAUTHOR {cout << "AUTHOR:" << *$2 << endl; nodotemporal.author=*$2; delete $2; $2=NULL;};
files:		/*none*/ | files file | files commondir;
commondir:	BCOMMONDIR ECOMMONDIR {cout << "COMMONDIR:" << *$2 << endl; delete $2; $2=NULL;};
file:		BFILE filedata EFILE;
filedata:	name cvsstate revision branch tags {nodotemporal.files+="\\l";};
name:		BNAME ENAME {cout << "NAME:" << *$2 << "\t"; nodotemporal.files+=*$2; delete $2; $2=NULL;};
cvsstate:	BCVSSTATE ECVSSTATE {cout << "CVSSTATE:" << *$2 << "\t"; delete $2; $2=NULL;};
revision:	BREVISION EREVISION {cout << "REVISON:" << *$2 << "\n"; delete $2; $2=NULL;};
branch:		/*none*/ | BBRANCH EBRANCH {cout << "BRANCH:" << *$2 << "\n"; nodotemporal.files+="["+*$2+"]"; delete $2; $2=NULL;};
tags:		/*none*/ | tags tag;
tag:		BTAG ETAG;
msg:		BMSG EMSG; 
tagdate:	BTAGDATE tagisodate tagdatetag ETAGDATE;
tagisodate: BTAGISODATE ETAGISODATE {cout << "TAGISODATE:" << *$2 << endl; delete $2; $2=NULL;};
tagdatetag:	BTAGDATETAG ETAGDATETAG {cout << "TAGDATETAG:" << *$2 << endl; delete $2; $2=NULL;};

%%
/*** Additional Code ***/
// We have to implement the error function
void Libcvs::LibcvsBisonParser::error(const Libcvs::LibcvsBisonParser::location_type &loc, const string &msg) {
	cerr << "Error: " << loc << "\t" << msg << endl;
}

#include "Libcvs.hh"
// Now that we have the Parser declared, we can declare the Scanner and implement the yylex function
static int yylex(Libcvs::LibcvsBisonParser::semantic_type * yylval, Libcvs::LibcvsFlexScanner &scanner) {
	return scanner.yylex(yylval);
}


